package org.xxpay.pay.channel.yeepay;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.entity.TransOrder;
import org.xxpay.pay.channel.BaseTransNotify;
import org.xxpay.pay.channel.yeepay.util.SignUtil;
import org.xxpay.pay.channel.yeepay.util.XmlUtils;
import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.HashMap;
import java.util.Map;

/**
 * 易宝代付回调
 */
@Service
public class YeepayTransNotifyService extends BaseTransNotify {

    private static final MyLog logger = MyLog.getLog(YeepayTransNotifyService.class);

    @Override
    public String getChannelName() {
        return YeepayConfig.CHANNEL_NAME_YEEPAY;
    }

    @Override
    public String doNotify(Object notifyData) {
        String logPrefix = "【处理易宝代付回调】";
        logger.info("====== 开始处理易宝代付回调通知 ======");
        JSONObject retObj = buildRetObj();
        try {
            HttpServletRequest req = (HttpServletRequest) notifyData;
            req.setCharacterEncoding("gbk");

            StringBuffer sb = new StringBuffer();
            InputStream is = req.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is,"UTF-8"));
            //读取HTTP请求内容
            String buffer = null;
            while ((buffer = br.readLine()) != null) {
                //在页面中显示读取到的请求参数
                sb.append(buffer);
            }
            String resXml = sb.toString();

            //[04]. 验签
            if(StringUtils.isEmpty(resXml)){ //无任何响应数据
                logger.info("{} >>> 请求失败", logPrefix);
                return buildFailRetObj().toString();
            }

            Map<String, String> reqMap = XmlUtils.xml2Map(resXml); ///将响应结果转换为map

            String reqCmd = reqMap.get("cmd"); //命令
            String reqMerId = reqMap.get("mer_Id"); //商编
            String reqBatchNo = reqMap.get("batch_No"); //batch_No 批次号
            String reqOrderId = reqMap.get("order_Id"); //订单号
            String reqStatus = reqMap.get("status"); //打款状态 S已到账 F失败
            String reqMessage = reqMap.get("message"); //描述
            String reqHmac = reqMap.get("hmac"); //签名信息

            logger.info("回调结果 cmd={}, mch_Id={}, batch_No={}, order_Id={}, status={}, message={}", reqCmd, reqMerId, reqBatchNo, reqOrderId, reqStatus, reqMessage);

            TransOrder transOrder = commonService.transOrderService.findByTransOrderId(reqOrderId);
            if (transOrder == null) {
                logger.error("transOrderId={}, db中无此订单", reqOrderId);
                return buildFailRetObj().toString();
            }

            YeepayConfig config = new YeepayConfig(getTransParam(transOrder));

            //返回结果验签字段及顺序： cmd, mer_Id, batch_No, order_Id, status, message, mchMmacKey
            String signSource = SignUtil.genSignSource(reqCmd, reqMerId, reqBatchNo, reqOrderId, reqStatus, reqMessage, config.getHmacKey());

            String signedContent = SignUtil.verifyHMAC(reqHmac); //获取原始签名串
            if(StringUtils.isEmpty(signedContent) || !signedContent.equals(signSource)){ //验签失败
                logger.info("{} >>> 验签失败", logPrefix);
                return buildFailRetObj().toString();
            }

            // 交易状态:失败/成功/已退票
            if("S".equals(reqStatus)) {// 成功

                logger.info("{} >>> 转账成功", logPrefix);
                return updateConfirmSuccess(transOrder, null) ?
                buildRet(config, reqBatchNo, reqOrderId, "S") : this.buildRet(config, reqBatchNo, reqOrderId, "F");

            }else if("F".equals(reqStatus) ){ // 失败

                logger.info("{} >>> 转账失败", logPrefix);
                return updateConfirmFail(transOrder, null, reqStatus, reqMessage) ?
                        buildRet(config, reqBatchNo, reqOrderId, "S") : this.buildRet(config, reqBatchNo, reqOrderId, "F");

            }else{
                //未知状态
                logger.error("{}返回状态【{}】未知，无法继续执行", logPrefix,reqStatus);
                return buildRet(config, reqBatchNo, reqOrderId, "F");
            }


        } catch (Exception e) {
            logger.error(e, logPrefix + "处理异常");
            return buildFailRetObj().toString();
        }

    }

    /**
     *  生成回调同步响应数据
     * @param config
     * @param batchNo
     * @param orderId
     * @param retCode 成功接收表示为 S
     * @return
     */
    private String buildRet(YeepayConfig config, String batchNo, String orderId, String retCode) {

        //封装响应参数
        Map<String, String> resXmlMap = new HashMap<>();
        resXmlMap.put("cmd", "TransferNotify");	//命令： 固定值TransferNotify
        resXmlMap.put("mer_Id", config.getMerId()); 	//实际发起付款的交易商户编号： 发起付款的总（分）公司在易宝支付的客户编号
        resXmlMap.put("batch_No", batchNo); 	//打款批次号: 不区分产品，必须唯一，要求长度范围15-20位的数字串
        resXmlMap.put("order_Id", orderId); //订单号
        resXmlMap.put("ret_Code", retCode); 	//成功接收表示为 S

        //签名字段及顺序： cmd、 mer_Id、 batch_No、order_Id、 ret_Code、 mchHmacKey
        String signSource = SignUtil.genSignSource(
                resXmlMap.get("cmd"),
                resXmlMap.get("mer_Id"),
                resXmlMap.get("batch_No"),
                resXmlMap.get("order_Id"),
                resXmlMap.get("ret_Code"),
                config.getHmacKey() );

        resXmlMap.put("hmac", SignUtil.sign(signSource, getCertFilePath(getChannelName(), payConfig.getCertRootPath(), config.getPfxFilePath()), config.getPfxPassword())); 	//签名信息

        return XmlUtils.toXml(resXmlMap);
    }
}
